feat(auth): in-app Twitch sign-in flow#78
Merged
ImpulseB23 merged 4 commits intomainfrom Apr 17, 2026
Merged
Conversation
Adds Tauri command surface and SignIn overlay so non-developers can sign in without running the prismoid_dcf CLI tool. Closes the OAuth UX gap in Phase 1.
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
There was a problem hiding this comment.
Pull request overview
This PR adds an in-app Twitch OAuth Device Code Grant (DCF) sign-in UX by exposing the existing Rust auth manager through new Tauri commands and a SolidJS SignIn overlay, plus wiring a wake-up notifier so the Windows sidecar supervisor can react immediately to login/logout.
Changes:
- Added a frontend auth client +
SignInoverlay that drives the DCF flow and gatesChatFeedon login state. - Added new Tauri commands (
twitch_auth_status,twitch_start_login,twitch_complete_login,twitch_cancel_login,twitch_logout) with sharedAuthState. - Updated the Windows sidecar supervisor to wait on a shared
Notify(with a 30s timeout fallback) instead of fixed sleeping.
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| apps/desktop/src/lib/twitchAuth.ts | New TS wrapper around Tauri Twitch auth commands + shell open helper. |
| apps/desktop/src/components/SignIn.tsx | New in-app sign-in overlay implementing the DCF UX and error mapping. |
| apps/desktop/src/App.tsx | Boot-time auth status check to switch between SignIn and ChatFeed. |
| apps/desktop/src-tauri/tauri.conf.json | Adjusts shell plugin open configuration for Twitch verification URLs. |
| apps/desktop/src-tauri/src/twitch_auth/mod.rs | Exposes new commands module and re-exports command/state types. |
| apps/desktop/src-tauri/src/twitch_auth/manager.rs | Adds peek_login() and logout() helpers for UI/supervisor. |
| apps/desktop/src-tauri/src/twitch_auth/commands.rs | New Tauri command surface + error mapping + unit tests. |
| apps/desktop/src-tauri/src/sidecar_supervisor.rs | Supervisor now receives shared AuthManager + Notify and waits on it in waiting_for_auth. |
| apps/desktop/src-tauri/src/lib.rs | Registers auth commands; builds/manages shared AuthState; passes shared auth + notifier to supervisor. |
- Switch wakeup notifier from notify_waiters() to notify_one() so the permit is stored if the supervisor isn't currently parked, preventing dropped login/logout signals. - Degrade gracefully when reqwest::Client::builder() fails in setup instead of panicking the app (per docs/stability.md). - Rename SignIn cancel button to "Start over" and add a generation counter so stale completeLogin() resolutions from a previous attempt can't accidentally authenticate the user.
Refactors the twitch_auth commands to delegate to inherent AuthState methods so they're directly testable without a Tauri AppHandle, then adds tests covering: status helper logged_in/logged_out paths, complete_login no_pending_flow path, logout permit-storing notify, cancel_login idempotency, and the remaining AuthError variants (Keychain, Json, Config).
Tauri command bodies can't be unit-tested without spinning up a Tauri runtime + WebView2 host (mock_runtime crashes with STATUS_ENTRYPOINT_NOT_FOUND on Windows). Standard pattern: keep #[tauri::command] functions as thin adapters and put all branchable logic in a separately-testable module. - Move AuthState, AuthStatus, DeviceCodeView, AuthCommandError, and the From<AuthError> impl into twitch_auth/auth_state.rs along with all unit tests (now reach 91.79% coverage on that file). - commands.rs is now ~50 lines of pure adapter delegation. Added to codecov ignore list alongside lib.rs and main.rs (same rationale: Tauri framework wiring without testable branches). - mod.rs re-exports updated; no external API change. 123 lib tests still pass, clippy clean.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes the Phase 1 OAuth UX gap by surfacing the existing Device Code Grant backend through Tauri commands and a SignIn overlay, so non-developers can run Prismoid without editing files or running CLI tools.
What's new
Tauri commands (
twitch_auth/commands.rs):twitch_auth_status— peeks the keychain to choose SignIn vs ChatFeedtwitch_start_login— kicks off DCF, returns user_code + verification_uritwitch_complete_login— awaits authorization, persists tokens, fires wakeuptwitch_cancel_login— clears the pending flow slottwitch_logout— wipes the keychain entry, fires wakeupShared state:
AuthState { manager: Arc<AuthManager>, pending: Mutex<Option<PendingDeviceFlow>>, wakeup: Arc<Notify> }. Supervisor and commands hold clones of the sameAuthManagerandNotify, so a successful sign-in wakes the supervisor'swaiting_for_authsleep within milliseconds instead of forcing a 30 s wait.Frontend (
App.tsx,components/SignIn.tsx,lib/twitchAuth.ts):twitch_auth_status→ splash → SignIn or ChatFeeduser_denied,device_code_expired,keychain,oauth,no_pending_flowCapability:
tauri.conf.jsonnow allowsshell.openonly forhttps://(?:id|www)\.twitch\.tv/.Tests
-D warningsThe
prismoid_dcfdev tool still works for headless seeding.